package plgdbv1

import (
	"dgo/MyProj/PrjHttpUtils"
	db_utils "dgo/goutils/db-utils"
	"dgo/goutils/utils"
	"dgo/plg/plgnet"
	"fmt"
	"gitee.com/ymofen/supervalue"
	"time"
)

type DBChecker struct {
	PlgBase
	intervalsecs int
	datasource   string
	cnt          int
	errcnt       int
	lastmsg      string
	msglst       *utils.SyncCycleList
	chksql       string
}

func (this *DBChecker) innerWork() {
	dao := db_utils.NewDBHelperEx(this.datasource)
	defer dao.Close()
	t0 := time.Now()
	rows, err := dao.Query(this.chksql)
	if err != nil {
		t1 := time.Since(t0)
		this.errcnt++
		this.lastmsg = fmt.Sprintf("[%s]耗时:%d(ms), err:%s", utils.NowString(), t1.Milliseconds(), err.Error())
		this.LogWarnMessage("sql:%s, err:%s", this.chksql, err.Error())
		return
	}
	defer rows.Close()
	t1 := time.Since(t0)
	this.lastmsg = fmt.Sprintf("[%s]耗时:%d(ms)", utils.NowString(), t1.Milliseconds())
	this.cnt++
	return
}

/*
*

	{
	  "id": "dbchk",
	  "type": "db.checker",
	  "conf": {
	     "datasource":"main",
	     "checksql":"select 1",
	     "interval":10
	  }
	}
*/
func (this *DBChecker) ReloadConf(conf *wrapper.SuperValue) error {
	if conf == nil {
		return nil
	}

	if this.msglst == nil {
		this.msglst = utils.NewSyncCycleList()
	}

	this.chksql = conf.StringByName("checksql", "")

	this.datasource = conf.StringByName("datasource", "")

	interval := time.Duration(conf.IntByName("interval", 10))
	if interval <= 0 {
		interval = 10
	}
	this.intervalsecs = int(interval)

	utils.DefaultPatrolTask().CheckStart()

	utils.DefaultPatrolTask().AddTask(this, time.Second*interval, func(id interface{}, args ...interface{}) {
		utils.DefaultWorkers().PostTaskFunc(this, this.innerWork)
	})
	return nil
}

func (this *DBChecker) Close() (err error) {
	this.PlgBase.Close()
	utils.DefaultPatrolTask().DelTask(this)
	return
}

func (this *DBChecker) OnHttpStatus(rec *plgnet.PlgHttpRec) (rval interface{}, errcode int, err error) {
	itype := rec.QryAsInt("type", 0)
	if itype == 99 {
		json := wrapper.NewSVObject()
		json.SetKeyValue("interval-secs", this.intervalsecs)
		json.SetKeyValue("cnt", fmt.Sprintf("err:%d, total:%d", this.errcnt, this.cnt))
		json.SetKeyValue("lastmsg", this.lastmsg)
		json.SetKeyValues("now", utils.NowString())
		PrjHttpUtils.JSON2TableRec(rec.RespW, "", json.AsJSONString(false))
	} else if itype == 98 {
		rec.ResponseSyncListNEx(this.msglst)
	} else if itype == 1 {
		//searchval := rec.QryAsString("searchval", "")
		json := wrapper.NewSVArray()
		//this.lstDevice.ListRangeV2(func(key, value interface{}) bool {
		//	//dev := value.(*YsledMqttWebServDevice)
		//	ok := true
		//	if len(searchval) > 0 {
		//
		//	}
		//	return ok
		//}, func(k0, v0, k1, v1 interface{}) bool {
		//	return true
		//}, func(key, val interface{}) bool {
		//	return true
		//})

		if rec.QryAsInt("json", 0) == 1 {
			PrjHttpUtils.ResponseAsJSON(rec.RespW, json.AsJSONStringEx(false, false))
		} else {
			PrjHttpUtils.JSON2Table(rec.RespW, "", json.AsJSONString(false))
		}
	} else {
		var sb utils.BytesBuilder
		PrjHttpUtils.AppendIndexBody(&sb, "status", "status?type=99")
		PrjHttpUtils.AppendIndexBody(&sb, "msglist", "status?type=98&n=100&searchval=")
		PrjHttpUtils.ResponseBodyHtml(rec.RespW, sb.String())
	}
	return
}

func (this *DBChecker) LogInfoMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_INFO, 1, s, args...)
}

func (this *DBChecker) LogWarnMessage(s string, args ...interface{}) {
	this.msglst.LogMsg(s, args...)
	utils.Log.Msgf(this.PlugId, utils.LogLV_WARN, 1, s, args...)
}

func CreateDBCheckerFunc(args ...interface{}) (rval interface{}, err error) {
	obj := &DBChecker{}

	if len(args) > 0 {
		if str, ok := args[0].(string); ok {
			obj.PlugId = str
		}
	}
	rval = obj
	return
}
